OpenCV.jsをJavaScript/Node.jsで使ってみた
こんにちは、CX事業本部 IoT事業部の若槻です。
今までOpenCVはPythonで使うものというイメージが強かったのですが、OpenCVのJavaScript実装であるOpenCV.jsなるものもあるみたいです。
今回は、OpenCV.jsをJavaScriptおよびNode.jsで使ってみました。
やってみた
OpenCV.jsの導入
まず準備としてOpenCV.jsの導入を行います。
下記よりOpenCVのソース(opencv-{VERSION_NUMBER}-docs.zip
)の最新版をダウンロードします。
解凍したソース内に含まれるopencv.js
を作業パスにコピーします。
JavaScriptで使ってみる
こちらのチュートリアルを参考に、OpenCV.jsをJavaScriptで使ってみます。
opencv.js
ファイルと同じパスに次のindex.html
を作成します。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello OpenCV.js</title> </head> <body> <h2>Hello OpenCV.js</h2> <p id="status">OpenCV.js is loading...</p> <div> <div class="inputoutput"> <img id="imageSrc" alt="No Image" /> <div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div> </div> <div class="inputoutput"> <canvas id="canvasOutput" ></canvas> <div class="caption">canvasOutput</div> </div> </div> <script type="text/javascript"> let imgElement = document.getElementById('imageSrc'); let inputElement = document.getElementById('fileInput'); inputElement.addEventListener('change', (e) => { imgElement.src = URL.createObjectURL(e.target.files[0]); }, false); imgElement.onload = function() { let mat = cv.imread(imgElement); cv.imshow('canvasOutput', mat); mat.delete(); }; function onOpenCvReady() { document.getElementById('status').innerHTML = 'OpenCV.js is ready.'; } </script> <script async src="opencv.js" onload="onOpenCvReady();" type="text/javascript"></script> </body> </html>
ブラウザでindex.html
を開きます。[ファイルを選択]をクリックして適当な画像ファイルをアップロードします。
すると画像を表示できました。上の画像は<img>
、下の画像は<canvas>
による表示です。
ポイントは下記の部分の記述です。
imgElement.onload = function() { let mat = cv.imread(imgElement); cv.imshow('canvasOutput', mat); mat.delete(); };
cv.imread()
で<img id="imageSrc" alt="No Image" />
から画像を取得しMat化しています。またcv.imshow()
によりMatを<canvas id="canvasOutput" ></canvas>
に出力することによりブラウザに表示しています。
Node.jsで使ってみる
続いて、こちらのチュートリアルを参考に、OpenCV.jsをNode.jsで使ってみます。
Minimal example
まず最小構成で動作を確認してみます。
opencv.js
ファイルと同じパスに次のexample1.js
を作成します。
// Define a global variable 'Module' with a method 'onRuntimeInitialized': Module = { onRuntimeInitialized() { // this is our application: console.log(cv.getBuildInformation()) } } // Load 'opencv.js' assigning the value to the global variable 'cv' cv = require('./opencv.js')
実行するとビルド情報が取得できます。
$ node example1.js
cv = require('./opencv.js')
でopencv.js
をロードし、ライブラリがreadyとなったらonRuntimeInitialized()
が実行されます。
Working with images
前節を踏まえ、実際に画像を処理してみます。
project1
ディレクトリ配下にnpmプロジェクトを作成します。
mkdir project1 cd project1 npm init -y npm install jimp
jimp
は画像の操作を簡単に行えるライブラリです。
また同パス内に、先程のopencv.js
および画像ファイルlena.jpg
を配置します。
今回配置した画像ファイルは下記です。
そして同パス内に下記のexampleNodeJimp.js
を作成します。
const Jimp = require('jimp'); async function onRuntimeInitialized(){ // load local image file with jimp. It supports jpg, png, bmp, tiff and gif: var jimpSrc = await Jimp.read('./lena.jpg'); // `jimpImage.bitmap` property has the decoded ImageData that we can use to create a cv:Mat var src = cv.matFromImageData(jimpSrc.bitmap); // following lines is copy&paste of opencv.js dilate tutorial: let dst = new cv.Mat(); let M = cv.Mat.ones(5, 5, cv.CV_8U); let anchor = new cv.Point(-1, -1); cv.dilate(src, dst, M, anchor, 1, cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue()); // Now that we are finish, we want to write `dst` to file `output.png`. For this we create a `Jimp` // image which accepts the image data as a [`Buffer`](https://nodejs.org/docs/latest-v10.x/api/buffer.html). // `write('output.png')` will write it to disk and Jimp infers the output format from given file name: new Jimp({ width: dst.cols, height: dst.rows, data: Buffer.from(dst.data) }) .write('output.png'); src.delete(); dst.delete(); } // Finally, load the open.js as before. The function `onRuntimeInitialized` contains our program. Module = { onRuntimeInitialized }; cv = require('./opencv.js');
実行するとoutput.png
ファイルが作成されます。
$ node example1.js
cv.dilate()
により境界をぼやけさせる画像変換を行えました。
おわりに
OpenCV.jsをJavaScriptおよびNode.jsで使ってみました。
今までOpenCVを使うときは当たり前のようにPythonを使っていたのですが、Webアプリやjs系プロジェクトでもOpenCVを利用できることが確認できてよかったです。これにより、例えばAWS Lambda(Node.jsランタイム)上などでも簡単な画像処理であればマネージドサービスを使わなくても出来そうですね。
以上